/* Context3D.m */

#import "Context3D.h"
#import "View3D.h"
#import <dpsclient/wraps.h>

@implementation Context3D
+ newFrame:(NXRect *)frameRect
{
	self=[super newFrame:frameRect];	
	pictureDistance=1500.0;
	clippingDistance=1.0;
	currentPoint.x=0.0;
	currentPoint.y=0.0;
	currentPoint.z=0.0;
	[self setContentView:[View3D new]];
	return self;
}

- moveto:(vector3D *)where
{
	currentPoint=*where;
	return self;
}

- lineto:(const vector3D *)where
{
	NXPoint start,end;
	vector3D current,to;
	if(currentPoint.z > -clippingDistance) {		// we make to be the point
		if(where->z > -clippingDistance) {			// less than clippingDistance
			currentPoint=*where;							// if there is one.
			return self;									// if both to and currentPoint
		}														// are closer than 
		to=currentPoint;									// clippingDistance, we return
		current=*where;									// out.
	}
	else {
		to=*where;
		current=currentPoint;
	}
	if(to.z > -clippingDistance) {					// if to is closer than
		float temp;											// clippingDistance, we
		vector3D tempVect;								// know from the above
		temp=current.z+clippingDistance;				// steps that current
		temp=temp/(current.z-to.z);					// is not.
		tempVect.x=to.x-current.x;						// We recalculate to such that
		tempVect.y=to.y-current.y;						// it is at the intersection
		tempVect.z=to.z-current.z;						// of the line segment and the
		to.x=current.x + tempVect.x*temp;			// clipping plane.
		to.y=current.y + tempVect.y*temp;
		to.z=current.z + tempVect.z*temp;				
	}
	
	// here we do a simple projection, since we now know that both current and
	// to are in front of the clipping plane.
		
	start.x=current.x*(-pictureDistance)/current.z;
	start.y=current.y*(-pictureDistance)/current.z;
	end.x=to.x*(-pictureDistance)/to.z;
	end.y=to.y*(-pictureDistance)/to.z;
	PSmoveto(start.x,start.y);
	PSlineto(end.x,end.y);
	PSstroke();
	currentPoint=*where;
	return self;	
}

- polygon:(vector3D *)vertices howMany:(int)count
{
	int ctr;
	[self moveto:&vertices[0]];
	for(ctr=1;ctr<count;++ctr)
		[self lineto:&vertices[ctr]];
	[self lineto:&vertices[0]];
	return self;
}

- contentView
{
	return contentView;
}

- setContentView:anObject
{
	contentView=anObject;
	[anObject setSuperView:self];
	return self;
}

- setPictureDistance:(float)dist
{
	if(dist > 0.0) {
		pictureDistance=dist;
		return self;
	}
	return nil;
}

- setClippingDistance:(float)dist
{
	if(dist > 0.0) {
		clippingDistance=dist;
		return self;
	}
	return nil;
}

- drawSelf:(const NXRect *) rects:(int)rectCount
{
	[contentView display];
	return self;
}

- free
{
	[contentView free];
	return [super free];
}

@end
